package com.inspectortime.webapp;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.inspectortime.domain.User;
import com.inspectortime.mail.service.AbstractMailMessage;
import com.inspectortime.mail.service.MailService;
import com.inspectortime.mail.service.StaticMailMessage;
import com.inspectortime.mail.service.StaticMailMessageTemplateNames;
import com.inspectortime.repository.Repository;

/**
 * TODO: Include and verify an expiration component in the token.
 * @author mkvalsvik
 * 
 */
public class ForgotPasswordFormController extends SimpleFormController {

	private static Log log = LogFactory
			.getLog(ForgotPasswordFormController.class);

	public ForgotPasswordFormController() {
		super();
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}

	public void setRepository(Repository repository) {
		this.repository = repository;
	}

	protected Map referenceData(HttpServletRequest request) throws Exception {
		return Collections.EMPTY_MAP;
	}

	private MailService mailService;
	private Repository repository;

	private static final String TEMP_RECEIVE_PASSWORD_RESET_CONTROLLER = "resetPassword.html";

	private String getResetLink(HttpServletRequest request, User user) {

		String requestedUrl = request.getRequestURL().toString();
		String resetLinkBaseUrl = requestedUrl.substring(0, requestedUrl
				.lastIndexOf("/"));

		return resetLinkBaseUrl + "/" + TEMP_RECEIVE_PASSWORD_RESET_CONTROLLER
				+ "?resetCode=" + user.getPasswordResetToken();
	}

	protected Object formBackingObject(HttpServletRequest request)
			throws Exception {
		LoginForm form = new LoginForm();
		return form;
	}

	protected ModelAndView onSubmit(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {

		LoginForm form = (LoginForm) command;

		ValidationUtils.rejectIfEmpty(errors, "userName", "required");
		if (errors.getErrorCount() > 0) {
			return new ModelAndView(getFormView(), errors.getModel());
		}

		User user = repository.findUserByEmailOrUserName(form.getUserName());
		if (user == null) {
			errors.rejectValue("userName", "notFound", null, "User not found");
			return new ModelAndView(getFormView(), errors.getModel());
		}

		// Generate and save new token
		String token = RandomStringUtils.randomAlphanumeric(20);
		user.setPasswordResetToken(token);
		user.save();

		// Send reset email
		Map<String, Object> props = new HashMap<String, Object>();
		props.put("user", user);
		props.put("resetLink", getResetLink(request, user));
		String toEmail = user.getEmail();
		String subject = "[InspectorTime] Your Password Reset Code";
		AbstractMailMessage message = new StaticMailMessage(StaticMailMessageTemplateNames.FORGOT_PASSWORD, props, toEmail, subject);
		this.mailService.send(message);

		return new ModelAndView(getSuccessView());

	}

}
